package com.wzdigit.wms.wms.controller.outbound;

import com.wzdigit.framework.exception.RestStatusException;
import com.wzdigit.framework.model.response.ErrorEntity;
import com.wzdigit.wms.basic.domain.transfer.GdnHeader;
import com.wzdigit.wms.basic.service.code.WhsPermService;
import com.wzdigit.wms.basic.util.HttpSessionUtil;
import com.wzdigit.wms.basic.client.PagerInfo;
import com.wzdigit.wms.basic.client.request.gdn.other.SearchOrderGoodsRequest;
import com.wzdigit.wms.basic.client.request.gdn.other.SearchOtherOutOrderRequest;
import com.wzdigit.wms.basic.client.request.gdn.other.SearchOtherOutSnRequest;
import com.wzdigit.wms.basic.client.request.gdn.other.SubmitOtherOutInputRequest;
import com.wzdigit.wms.basic.client.response.Result;
import com.wzdigit.wms.basic.client.response.basic.WarehouseApiResponse;
import com.wzdigit.wms.basic.client.response.gdn.other.OtherOutOrderGoodsResponse;
import com.wzdigit.wms.basic.client.response.gdn.other.OtherOutOrderInfoResponse;
import com.wzdigit.wms.basic.client.response.gdn.other.ScanOtherOutOrderResponse;
import com.wzdigit.wms.basic.client.response.gdn.other.ScanOtherOutSnResponse;
import com.wzdigit.wms.wms.constant.WmsWareConstant;
import com.wzdigit.wms.wms.service.across.CallbackService;
import com.wzdigit.wms.wms.service.basic.WarehouseService;
import com.wzdigit.wms.wms.service.core.GdnManagerService;
import com.wzdigit.wms.wms.service.order.OtherStockOutService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiResponse;
import io.swagger.annotations.ApiResponses;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.util.List;
import java.util.stream.Collectors;

@RestController
@Api(tags = "其他出库(out)")
@RequestMapping(value = WmsWareConstant.API_VERSION)
public class OtherStockOutController {

    private final String REQUEST_MODEL = "/OtherStockOut";

    @Autowired
    private RedissonClient redisson;

    @Autowired
    private OtherStockOutService service;
    @Autowired
	private WhsPermService whsPremService;

    @ApiOperation(value = "获取其他出库任务（分页）", notes = "获取其他出库任务（分页）")
    @ApiResponses({@ApiResponse(code = 500, message = "系统出现异常", response = ErrorEntity.class)})
    @RequestMapping(value = REQUEST_MODEL + "/search", method = RequestMethod.GET)
    public PagerInfo<List<OtherOutOrderInfoResponse>> search(
            SearchOtherOutOrderRequest input,
            HttpServletRequest servletRequest,
            HttpServletResponse servletResponse
    ) {
        try {
            // 查询当前用户权限仓库
            List<WarehouseApiResponse> whList = whsPremService.getWarehousePerm(servletRequest);
            input.setRangeWhsIds(whList.stream().map(WarehouseApiResponse::getWhsId).distinct().collect(Collectors.toList()));
            return this.service.search(input);
        } catch (RestStatusException e) {
            e.printStackTrace();
            servletResponse.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
            throw e;
        }
    }

    /**
     * 扫描工单
     *
     * @return
     */
    @ApiOperation(value = "扫描单号", notes = "扫描单号")
    @ApiResponses({@ApiResponse(code = 500, message = "系统出现异常", response = ErrorEntity.class)})
    @RequestMapping(value = REQUEST_MODEL + "/scanOrder", method = RequestMethod.GET)
    public Result<ScanOtherOutOrderResponse> scanOrder(String billNo,
                                                       HttpServletRequest servletRequest,
                                                       HttpServletResponse servletResponse) {
        try {
            ScanOtherOutOrderResponse ret = this.service.scanOrder(billNo);
            return new Result<ScanOtherOutOrderResponse>(true, "", ret);
        } catch (RestStatusException ex) {
            servletResponse.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
            throw ex;
        }
    }

    /**
     * 获取 sn 信息（分页）
     *
     * @param input
     * @param servletRequest
     * @param servletResponse
     * @return
     */
    @ApiOperation(value = "获取 sn 信息（分页）", notes = "获取 sn 信息（分页）")
    @ApiResponses({@ApiResponse(code = 500, message = "系统出现异常", response = ErrorEntity.class)})
    @RequestMapping(value = REQUEST_MODEL + "/searchOrderGoods", method = RequestMethod.GET)
    public PagerInfo<List<OtherOutOrderGoodsResponse>> searchOrderGoods(SearchOrderGoodsRequest input,
                                                                        HttpServletRequest servletRequest,
                                                                        HttpServletResponse servletResponse) {
        try {
            return this.service.searchOrderGoods(input);
        } catch (RestStatusException e) {
            e.printStackTrace();
            servletResponse.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
            throw e;
        }
    }

    /**
     * 扫描sn
     *
     * @return
     */
    @ApiOperation(value = "扫描SN", notes = "扫描SN")
    @ApiResponses({@ApiResponse(code = 500, message = "系统出现异常", response = ErrorEntity.class)})
    @RequestMapping(value = REQUEST_MODEL + "/scanSn", method = RequestMethod.POST)
    public Result<ScanOtherOutSnResponse> scanSn(@Valid @RequestBody SearchOtherOutSnRequest input,
                                                 HttpServletRequest servletRequest,
                                                 HttpServletResponse servletResponse) {
        try {
            ScanOtherOutSnResponse ret = this.service.scanSn(input);
            return new Result<>(ret);
        } catch (RestStatusException ex) {
            servletResponse.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
            throw ex;
        }
    }

    /**
     * 提交
     *
     * @return
     * @throws Exception 
     */
    @ApiOperation(value = "提交数据", notes = "提交数据")
    @ApiResponses({@ApiResponse(code = 500, message = "系统出现异常", response = ErrorEntity.class)})
    @RequestMapping(value = REQUEST_MODEL + "/submit", method = RequestMethod.POST)
    public Result<Boolean> submit(@Valid @RequestBody SubmitOtherOutInputRequest input,
                                  HttpServletRequest servletRequest,
                                  HttpServletResponse servletResponse) throws Exception {
        try {
            String userName = HttpSessionUtil.getLoginName(servletRequest);
            input.setUserName(userName);
            Boolean isClose = false;
            String key = "Key_Out_Order_" + input.getGdnNo();
            RLock lock = redisson.getLock(key);
            try {
                boolean status = lock.tryLock();
                if (status) {
                    isClose = this.service.submit(input);
                }
            } finally {
                // 当前线程获取到锁再释放锁
                if (lock != null && lock.isHeldByCurrentThread()) {
                    lock.unlock();
                }
            }
            return new Result<>(true, "操作成功", isClose);
        } catch (RestStatusException ex) {
            servletResponse.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
            throw ex;
        }
    }

    /**
     * 提交
     *
     * @return
     */
    @ApiOperation(value = "强制关闭", notes = "强制关闭")
    @ApiResponses({@ApiResponse(code = 500, message = "系统出现异常", response = ErrorEntity.class)})
    @RequestMapping(value = REQUEST_MODEL + "/close", method = RequestMethod.POST)
    public Result close(String billNo,
                        HttpServletRequest servletRequest,
                        HttpServletResponse servletResponse) {
        try {
            String userName = HttpSessionUtil.getLoginName(servletRequest);

            String key = "Key_Out_Order_" + billNo;
            RLock lock = redisson.getLock(key);
            try {
                boolean status = lock.tryLock();
                if (status) {
                    this.service.close(billNo, userName);
                }
            } finally {
                // 当前线程获取到锁再释放锁
                if (lock != null && lock.isHeldByCurrentThread()) {
                    lock.unlock();
                }
            }
            return new Result(true, "操作成功！");
        } catch (RestStatusException ex) {
            servletResponse.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
            throw ex;
        }
    }


    @Autowired
    private GdnManagerService gdnManagerService;
    @Autowired
    private CallbackService callbackService;

    /**
     * 提交
     *
     * @return
     */
    @ApiOperation(value = "写入SAP回传信息", notes = "写入SAP回传信息")
    @ApiResponses({@ApiResponse(code = 500, message = "系统出现异常", response = ErrorEntity.class)})
    @RequestMapping(value = REQUEST_MODEL + "/sapInfoWrite", method = RequestMethod.POST)
    public Result sapInfoWrite(String billNo,
                               HttpServletRequest servletRequest,
                               HttpServletResponse servletResponse) {
        try {
            GdnHeader gdnHeader = this.gdnManagerService.selectByNo(billNo);
            this.callbackService.Callback(gdnHeader);
            return new Result(true, "操作成功！");
        } catch (RestStatusException ex) {
            servletResponse.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
            throw ex;
        }
    }
}
